package com.tamecode.flowable;

import com.tamecode.listener.MyEventListener;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricActivityInstanceQuery;
import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

/**
 * @Author: LiQiongchao
 * @Date: 2021/8/8 9:08
 */
public class HolidayRequest {

    public static void main(String[] args) {

        // 定义工作流
        ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8")
                .setJdbcDriver("com.mysql.jdbc.Driver")
                .setJdbcUsername("root")
                .setJdbcPassword("root")
                // true: 构建引擎时，检查并在需要时更新表结构。表结构不存在则会创建。
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        ProcessEngine processEngine = configuration.buildProcessEngine();

        doHolidayRequest(processEngine);
    }

    public static void doHolidayRequest(ProcessEngine processEngine) {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 部署工作流
        Deployment deployment = repositoryService
                .createDeployment().addClasspathResource("holiday-request.bpmn20.xml")
                .deploy();

        // 查询
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
        System.out.println("Found process definition: " + processDefinition.getName());

        // 交互
        Scanner scanner = new Scanner(System.in);
        System.out.println("Who are you?");
        String employee = scanner.nextLine();
//        String employee = "Lee";

        System.out.println("How many holidays do u want to request?");
        Integer nrOfHolidays = Integer.parseInt(scanner.nextLine());
//        Integer nrOfHolidays = 2;

        System.out.println("Why do you need them?");
        String description = scanner.nextLine();
//        String description = "Go home.";

        // 运行
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("employee", employee);
        variables.put("nrOfHolidays", nrOfHolidays);
        variables.put("description", description);
        // key 即为 process 的 id ,<process id="holidayRequest" name="Holiday Request" isExecutable="true">
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinition.getKey(), variables);

        // 查询 managers 组的任务
        TaskService taskService = processEngine.getTaskService();
        TaskQuery taskQuery = taskService.createTaskQuery();
        List<Task> managers = taskQuery.taskCandidateGroup("managers").list();
        System.out.println("You have " + managers.size() + " tasks.");
        for (int i = 0; i < managers.size(); i++) {
            System.out.println((i + 1) + ") " + managers.get(i).getName());
        }

        // 完成任务
        System.out.println("Which task would you like to complete?");
        Integer taskIndex = Integer.valueOf(scanner.nextLine());
        Task task = managers.get(taskIndex - 1);
        Map<String, Object> processVariables = taskService.getVariables(task.getId());
        System.out.println(processVariables.get("employee") + " wants " + processVariables.get("nrOfHolidays") + "of holidays, Do you approve this?");

        // 批准流程
        boolean approved = scanner.nextLine().toLowerCase().equals("y");
        variables = new HashMap<>();
        variables.put("approved", approved);
        taskService.complete(task.getId(), variables);

        // 使用历史数据，显示任务已经执行的时间。显示任务在各个执行阶段花费的时间。
        HistoryService historyService = processEngine.getHistoryService();
        List<HistoricActivityInstance> activities = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstance.getId())
                .finished()
                .orderByHistoricActivityInstanceEndTime().asc()
                .list();
        for (HistoricActivityInstance activity : activities) {
            System.out.println(activity.getActivityId() + " took "
                    + activity.getDurationInMillis() + " milliseconds");
        }

        // 运行时添加和删除监听器，运行时修改的监听，在重启后不会保留记录。
//        MyEventListener myEventListener = new MyEventListener();
//        runtimeService.addEventListener(myEventListener);
//        runtimeService.removeEventListener(myEventListener);
    }

}
